home *** CD-ROM | disk | FTP | other *** search
/ Aminet 30 / Aminet 30 (1999)(Schatztruhe)[!][Apr 1999].iso / Aminet / gfx / misc / gnuplot-3.7src.lha / gnuplot-3.7src / gnuplot-3.7.lha / gnuplot-3.7 / term / mif.trm < prev    next >
Text File  |  1999-01-12  |  26KB  |  893 lines

  1. /*
  2.  * $Id: $
  3.  */
  4. /* GNUPLOT -- mif.trm */
  5.  
  6. /*[
  7.  * Copyright 1992, 1993, 1998
  8.  *
  9.  * Permission to use, copy, and distribute this software and its
  10.  * documentation for any purpose with or without fee is hereby granted,
  11.  * provided that the above copyright notice appear in all copies and
  12.  * that both that copyright notice and this permission notice appear
  13.  * in supporting documentation.
  14.  *
  15.  * Permission to modify the software is granted, but not the right to
  16.  * distribute the complete modified source code.  Modifications are to
  17.  * be distributed as patches to the released version.  Permission to
  18.  * distribute binaries produced by compiling modified sources is granted,
  19.  * provided you
  20.  *   1. distribute the corresponding source modifications from the
  21.  *    released version in the form of a patch file along with the binaries,
  22.  *   2. add special version identification to distinguish your version
  23.  *    in addition to the base release version number,
  24.  *   3. provide your name and address as the primary contact for the
  25.  *    support of your modified version, and
  26.  *   4. retain our contact information in regard to use of the base
  27.  *    software.
  28.  * Permission to distribute the released version of the source code along
  29.  * with corresponding source modifications in the form of a patch file is
  30.  * granted with same provisions 2 through 4 for binary distributions.
  31.  *
  32.  * This software is provided "as is" without express or implied warranty
  33.  * to the extent permitted by applicable law.
  34. ]*/
  35.  
  36. /*
  37.  * This file is included by ../term.c.
  38.  *
  39.  * This terminal driver was developed for
  40.  *      gnuplot for unix version 3.0 (patchlevel 1)
  41.  *      gnuplot for unix version 3.2 (patchlevel 2)
  42.  *
  43.  * This terminal driver supports:
  44.  *      Frame Maker MIF format version 3.00
  45.  *
  46.  * Options for this terminal driver (set terminal mif [options]):
  47.  *      colour /        Draw primitives with line types >= 0 in colour (sep. 2-7)
  48.  *      monochrome      Draw primitives in black (sep. 0)
  49.  *
  50.  *      polyline /      Draw lines as continous curves
  51.  *      vectors         Draw lines as collections of vectors
  52.  *
  53.  *      help / ?        Print short usage description on stderr
  54.  *
  55.  * Properties for this terminal driver:
  56.  *     -Gnuplot size of worksheet:              MIF_XMAX * MIF_YMAX
  57.  *     -Unit in MIF output:                     cm
  58.  *     -Plot primitives with the same pen will
  59.  *      be grouped in the same MIF group.
  60.  *     -Plot primitives with line types >= 0
  61.  *      will as default be drawn in colour.
  62.  *     -Lines are plotted as collections of
  63.  *      vectors, or as continous lines (default)
  64.  *     -Plot primitives in a plot will be in a
  65.  *      Frame in MIF. Several plot Frames will
  66.  *      be collected in one large Frame.
  67.  *     -Point size of MIF output characters:    MIF_PSIZE
  68.  *     -Used font for MIF output characters:    Times
  69.  *     -Supports vertical text
  70.  *     -points and dots as characters
  71.  *     -character formats for TextLines
  72.  *
  73.  * AUTHORS:
  74.  *      Olof Franksson, Physics IV, KTH, S-100 44 Stockholm, Sweden
  75.  * 
  76.  * NEW TERMINAL FORMAT:  David C. Schooley
  77.  
  78.  * COMMENTS:
  79.  *      Send comments and/or suggestions to olof@fysik4.kth.se
  80.  * 
  81.  * CHANGES:
  82.  *        Changed to new terminal format 9/29/95            schooley@ee.gatech.edu
  83.  *      Changed order of routine declarations.          olof@fysik4.kth.se
  84.  *      Changed mechanism for pen pattern selection.    kssingvo@immd4.informatik.uni-erlangen.de
  85.  *      Support for vertical text.                      kssingvo@immd4.informatik.uni-erlangen.de
  86.  *      Fixed plot bug for "set size XS,YS", XS/YS > 1. olof@fysik4.kth.se
  87.  *
  88.  */
  89.  
  90. #include "driver.h"
  91.  
  92. #ifdef TERM_REGISTER
  93. register_term(mif)
  94. #endif
  95.  
  96.  
  97.  
  98. #ifdef TERM_PROTO
  99. TERM_PUBLIC void MIF_init __PROTO((void));
  100. TERM_PUBLIC void MIF_graphics __PROTO((void));
  101. TERM_PUBLIC void MIF_text __PROTO((void));
  102. TERM_PUBLIC void MIF_linetype __PROTO((int linetype));
  103. TERM_PUBLIC void MIF_move __PROTO((unsigned int x, unsigned int y));
  104. TERM_PUBLIC void MIF_vector __PROTO((unsigned int x, unsigned int y));
  105. TERM_PUBLIC void MIF_put_text __PROTO((unsigned int x, unsigned int y, char *str));
  106. TERM_PUBLIC int MIF_text_angle __PROTO((int ang));
  107. TERM_PUBLIC void MIF_reset __PROTO((void));
  108. TERM_PUBLIC void MIF_options __PROTO((void));
  109. TERM_PUBLIC int MIF_justify_text __PROTO((enum JUSTIFY mode));
  110. TERM_PUBLIC void MIF_point __PROTO((unsigned int x, unsigned int y, int number));
  111.  
  112. /** Coordinates **/
  113. /* The cast to float is not necessary because we are dividing by a float */
  114. /* On OSK the cast to a float is not allowed in a constant expression wich */
  115. /* is used by the declaration and initialization of mif_line */
  116. /* Converts gnuplot units to MIF units */
  117. #define GNP_TO_MIF(P)   ((P) / 1000.0)
  118. /* Basic unit: 0.01 mm (15cm -> 15*10*100=15000) */
  119. #define MIF_XMAX 15000
  120. /* Basic unit: 0.01 mm (10cm -> 10*10*100=10000) */
  121. #define MIF_YMAX 10000
  122.  
  123. #define MIF_XLAST (MIF_XMAX - 1)
  124. #define MIF_YLAST (MIF_YMAX - 1)
  125.  
  126. static int insert_mif_line __PROTO((double fx, double fy));
  127. static int proc_group_id __PROTO((int group_id));
  128. static void free_mif_line __PROTO((void));
  129. static void put_mif_line __PROTO((void));
  130. static void MIF_set_font __PROTO((char *));
  131. static void mif_put_point __PROTO((unsigned int x, unsigned int y, int np));
  132.  
  133. #ifndef cfree
  134. # define cfree free
  135. #endif
  136.  
  137. /* Declared in ../setshow.c */
  138. extern char term_options[];
  139.  
  140. /* From version.c */
  141. extern char version[];
  142. extern char patchlevel[];
  143.  
  144. static struct mif_line {    /* Line point structure specification */
  145.     float fpos_x;        /* Line point X coordinate */
  146.     float fpos_y;        /*            Y coordinate */
  147.     struct mif_line *next;    /* Pointer to next line point */
  148.     struct mif_line *prev;    /* Pointer to previous line point */
  149. } mif_line =
  150. {                /* Current position structure. Adjust for orign. Local for this file. */
  151.     GNP_TO_MIF(0),
  152.     GNP_TO_MIF(MIF_YLAST),
  153.     &mif_line,
  154.     &mif_line
  155. };
  156.  
  157. /** Characters **/
  158. #define MIF_PSIZE 9        /* Point size of used characters */
  159.  
  160. #define MIF_VCHAR (MIF_YMAX/31)    /* Distance between rows (a guess) */
  161. #define MIF_HCHAR (MIF_XMAX/95)    /* Distance between characters (a guess) */
  162.  
  163. /** Scale marks **/
  164. #define MIF_VTIC  (MIF_YMAX/150)    /* Size of scale mark (vert) */
  165. #define MIF_HTIC  (MIF_XMAX/225)    /* Size of scale mark (hor) */
  166.  
  167. /** Drawing properties **/
  168. static char mif_justify[64];    /* How to justify the used text */
  169. static char mif_pen[64], mif_pen_width[64], mif_separation[64];        /* How to plot */
  170.  
  171. #define MIF_TEXT_HOR  0
  172. #define MIF_TEXT_VER  1
  173. static int mif_text_ang = MIF_TEXT_HOR;        /* Rotation angle of text */
  174.  
  175. #define MIF_NPENS 16        /* Number of MIF pen types */
  176. static int mif_pentype = 0;    /* Pen type to use. Also used to create groups for graphics */
  177. #define MIF_PEN_TO_GROUP(P)     ( 1 + (P) )    /* Map pen type to group number. Must be >= 1 */
  178.  
  179. static int mif_pattern_table[MIF_NPENS] =
  180. { /* Table, which pattern should be used for drawing */
  181.     0,                /* border  */
  182.     1,                /* not used */
  183.     2, 3, 4, 8, 12, 13,        /* other lines: functions, data, ... (5 is used for grid; 6,7 is (nearly) invisible) */
  184.     5,                /* grid */
  185.     9, 10, 11, 12, 13, 14, 15    /* not used */
  186. };
  187.  
  188. /** MIF groups administration **/
  189. #define MIF_NGROUP_ID           20
  190. static struct mif_group_id {
  191.     int group_existance;
  192. /* This group id should generate a MIF group */
  193. #define MIF_GROUP_EXISTS        1
  194. /* This group id should not generate a MIF group */
  195. #define MIF_GROUP_NOT_EXISTS    0
  196.  
  197.     int group_id;
  198. #define MIF_INVALID_GROUP_ID    0    /* An invalid MIF group ID */
  199.  
  200. } mif_group_id[MIF_NGROUP_ID];    /* List of used group ID:s and corresponding MIF groups existance */
  201.  
  202. /** Semaphores **/
  203. static int mif_initialized = 0;    /* != 0 when output is active */
  204. static int mif_in_frame = 0;    /* != 0 when inside a plot frame */
  205. static int mif_frameno = -1;    /* Current frame number */
  206. static int mif_colour = TRUE;    /* == TRUE when colour should be used */
  207. static int mif_polyline = TRUE;    /* == TRUE when lines are drawn as continous curves */
  208.  
  209. struct mpt {            /* point definition structure */
  210.     int chr;            /* character for point */
  211.     float x_offset, y_offset;    /* offset for vertical positioning */
  212.     char *font;            /* font */
  213. };
  214.  
  215. char zgnuplot[] = "ZGnuplot";    /* character formats */
  216. char zgnuplotp[] = "ZGnuplotP";
  217. char zgnuplotd[] = "ZGnuplotD";
  218. char *mif_font = NULL;        /* actual character format */
  219.  
  220. struct mpt mpt[POINT_TYPES + 1] =
  221. {                /* point definition data */
  222.     {'.', 0.000, 0.005, zgnuplotd, /* dot */ },
  223.  
  224.     {'G', 0.002, 0.084, zgnuplotp, /* diamond */ },
  225.     {';', 0.002, 0.084, zgnuplotp, /* plus */ },
  226.     {'n', 0.002, 0.084, zgnuplotp, /* box */ },
  227.     {'5', 0.002, 0.084, zgnuplotp, /* X */ },
  228.     {'s', 0.002, 0.062, zgnuplotp, /* triangle */ },
  229.     {'K', 0.005, 0.075, zgnuplotp, /* star */ },
  230. };
  231.  
  232. /* diamond is offset 0, dot is offset -1 */
  233. struct mpt *mif_point = &(mpt[1]);
  234.  
  235. #endif
  236.  
  237.  
  238. #ifndef TERM_PROTO_ONLY
  239. #ifdef TERM_BODY
  240.  
  241.  
  242. /** Declaration of routine/s for internal use **/
  243. static int insert_mif_line __PROTO((double fx, double fy));
  244. static int proc_group_id __PROTO((int group_id));
  245.  
  246. /** Routine/s **/
  247.  
  248. /* Called when this terminal type is set in order to parse options */
  249. TERM_PUBLIC void MIF_options()
  250. {
  251.     if (!END_OF_COMMAND) {
  252.     /* Colour options */
  253.     if (!END_OF_COMMAND && almost_equals(c_token, "m$onochrome")) {        /* Compare up to $ */
  254.         mif_colour = FALSE;
  255.         c_token++;
  256.     }
  257.     if (!END_OF_COMMAND && (almost_equals(c_token, "c$olor")
  258.                 || almost_equals(c_token, "c$olour"))) {    /* Compare up to $ */
  259.         mif_colour = TRUE;
  260.         c_token++;
  261.     }
  262.     /* Curve options */
  263.     if (!END_OF_COMMAND && almost_equals(c_token, "v$ectors")) {    /* Compare up to $ */
  264.         mif_polyline = FALSE;
  265.         c_token++;
  266.     }
  267.     if (!END_OF_COMMAND && almost_equals(c_token, "p$olyline")) {    /* Compare up to $ */
  268.         mif_polyline = TRUE;
  269.         c_token++;
  270.     }
  271.     /* Short help */
  272.     if (!END_OF_COMMAND &&
  273.         (almost_equals(c_token, "h$elp") ||
  274.          almost_equals(c_token, "?$"))) {    /* Compare up to $ */
  275.         fprintf(stderr, "\
  276. Usage: set terminal mif [options]\n\
  277. \toptions:\n\
  278. \t\tcolour /        Draw primitives with line types >= 0 in colour (sep. 2-7)\n\
  279. \t\tmonochrome      Draw primitives in black (sep. 0)\n\n\
  280. \t\tpolyline /      Draw lines as continous curves\n\
  281. \t\tvectors         Draw lines as collections of vectors\n\n\
  282. \t\thelp / ?        Print short usage description on stderr\n");
  283.  
  284.         c_token++;
  285.     }
  286.     }
  287.     sprintf(term_options, "%s %s", (mif_colour == TRUE) ? "colour" : "monochrome",
  288.         (mif_polyline == TRUE) ? "polyline" : "vectors");
  289. }
  290.  
  291. /* Deallocate the used line structure elements */
  292. static void free_mif_line()
  293. {
  294.     struct mif_line *tline;
  295.  
  296.     while (mif_line.prev != &mif_line) {
  297.     /* Unlink */
  298.     tline = mif_line.prev;
  299.     mif_line.prev = mif_line.prev->prev;
  300.     mif_line.prev->next = &mif_line;
  301.  
  302.     /* Deallocate */
  303.     free(tline);
  304.     }
  305.  
  306.     /* Make sure that the list will be empty */
  307.     mif_line.prev = &mif_line;
  308.     mif_line.next = &mif_line;
  309. }
  310.  
  311. /* Draw the pending line. Change current position. */
  312. static void put_mif_line()
  313. {
  314.     int np, i;
  315.     struct mif_line *tline;
  316.  
  317.     /* Process if inside a Frame */
  318.     if (mif_initialized != 0 && mif_in_frame != 0) {
  319.  
  320.     /* Count the number of available points */
  321.     for (tline = mif_line.next, np = 1; tline != &mif_line; tline = tline->next, np++);
  322.  
  323.     /* Draw line (at least two points) */
  324.     if (np >= 2) {
  325.  
  326.         /* Line preamble */
  327.         fprintf(gpoutfile, "\t<PolyLine <GroupID %d> %s %s %s\n",
  328.             MIF_PEN_TO_GROUP(mif_pentype), mif_pen, mif_pen_width, mif_separation);
  329.  
  330.         /* Draw the line elements */
  331.         fprintf(gpoutfile, "\t\t<NumPoints %d> ", np);
  332.         for (i = 0, tline = &mif_line; i < np; i++, tline = tline->next) {
  333.         if (i % 4 == 0)
  334.             fputs("\n\t\t", gpoutfile);
  335.         fprintf(gpoutfile, "<Point  %.3f %.3f> ",
  336.             tline->fpos_x, tline->fpos_y);
  337.         }
  338.  
  339.         /* Line post amble */
  340.         fputs("\n\t>\n", gpoutfile);
  341.  
  342.         /* Register the used group ID */
  343.         proc_group_id(MIF_PEN_TO_GROUP(mif_pentype));
  344.  
  345.         /* Avoid to redraw this. The MIF system should remember it. */
  346.         mif_pen[0] = '\0';
  347.         mif_pen_width[0] = '\0';
  348.         mif_separation[0] = '\0';
  349.  
  350.         /* Move current position to end of line */
  351.         mif_line.fpos_x = mif_line.prev->fpos_x;
  352.         mif_line.fpos_y = mif_line.prev->fpos_y;
  353.  
  354.         /* Restore the line */
  355.         free_mif_line();
  356.     }
  357.     }                /* Line processed */
  358. }
  359.  
  360.  
  361. /* Draw a point */
  362. static void mif_put_point(x, y, np)
  363. unsigned int x, y;
  364. int np;
  365. {
  366.     /* Process if inside a Frame */
  367.     if (mif_initialized != 0 && mif_in_frame != 0) {
  368.  
  369.     /* Draw pending line */
  370.     if (mif_polyline == TRUE)
  371.         put_mif_line();
  372.  
  373.     /* Adjust current position for text-graphics alignment */
  374.     MIF_move(x, y);
  375.  
  376.     /* center text */
  377.     MIF_justify_text(CENTRE);
  378.  
  379.     /* Draw the point */
  380.     fprintf(gpoutfile, "\t<TextLine <GroupID %d>\n",
  381.         MIF_PEN_TO_GROUP(mif_pentype));
  382.  
  383.     MIF_set_font(mif_point[np].font);
  384.  
  385.     fprintf(gpoutfile, "\t\t<TLOrigin  %.3f %.3f> %s <String `%c'>\n",
  386.         mif_line.fpos_x + mif_point[np].x_offset,
  387.         mif_line.fpos_y + mif_point[np].y_offset,
  388.         mif_justify,
  389.         mif_point[np].chr);
  390.     fputs("\t>\n", gpoutfile);
  391.  
  392.     /* Register the used group ID */
  393.     proc_group_id(MIF_PEN_TO_GROUP(mif_pentype));
  394.  
  395.     /* Avoid to redraw this. The MIF system should remember it. */
  396.     mif_justify[0] = '\0';
  397.  
  398.     }                /* Point processed */
  399. }
  400.  
  401.  
  402. /*
  403.  *  draw points
  404.  */
  405. TERM_PUBLIC void MIF_point(x, y, number)
  406. unsigned int x, y;
  407. int number;
  408. {
  409.     if (number < 0) {        /* dot */
  410.     number = -1;
  411.     } else {            /* point */
  412.     number %= POINT_TYPES;
  413.     }
  414.     mif_put_point(x, y, number);
  415. }
  416.  
  417.  
  418. /* Set up a MIF output file */
  419. TERM_PUBLIC void MIF_init()
  420. {
  421.     int i;
  422.  
  423.     /* Process if not inside a MIF file and Frame */
  424.     if (mif_initialized == 0 && mif_in_frame == 0) {
  425.     /* Tell this terminal driver that the output is initialized and no current frames are processed */
  426.     mif_initialized = 1;
  427.     mif_in_frame = 0;
  428.  
  429.     /* Reset internal position */
  430.     free_mif_line();
  431.     mif_line.fpos_x = GNP_TO_MIF(0);
  432.     mif_line.fpos_y = GNP_TO_MIF(MIF_YLAST);
  433.  
  434.     /* Reset drawing properties strings */
  435.     mif_pen[0] = '\0';
  436.     mif_pen_width[0] = '\0';
  437.     mif_separation[0] = '\0';
  438.  
  439.     MIF_justify_text(LEFT);
  440.  
  441.     /* Reset group ID generator */
  442.     for (i = 0; i < MIF_NGROUP_ID; i++) {
  443.         mif_group_id[i].group_id = MIF_INVALID_GROUP_ID;
  444.         mif_group_id[i].group_existance = MIF_GROUP_NOT_EXISTS;
  445.     }
  446.  
  447.     /* Identify ourselves */
  448.     /*bs show borders */
  449.     /* Setup a default environment to use */
  450.     fprintf(gpoutfile, "\
  451. <MIFFile 3.00> # Generated by gnuplot version %s patchlevel %s; identifies this as a MIF file\n\
  452. #\n\
  453. # show borders\n\
  454. <Document\n<DBordersOn Yes>\n>\n\
  455. # Set a default pen pattern, pen width, unit and font for subsequent objects\n\
  456. <Pen 0>\n\
  457. <Fill 15>\n\
  458. <PenWidth 0.5 pt>\n\
  459. <Separation 0>\n\
  460. <Units Ucm>\n\
  461. <FontCatalog\n\
  462. \t<Font <FTag `%s'><FFamily `Times'><FSize %d><FPlain Yes>>\n\
  463. \t<Font <FTag `%s'><FFamily `ZapfDingbats'><FSize 7.0 pt><FPlain Yes>>\n\
  464. \t<Font <FTag `%s'><FFamily `Symbol'><FSize 5.0 pt><FPlain Yes>>\n\
  465. >\n\
  466. #\n",
  467.         version, patchlevel,
  468.         zgnuplot, MIF_PSIZE,
  469.         zgnuplotp,
  470.         zgnuplotd);
  471.     }                /* MIF file created */
  472. }
  473.  
  474. /* Finish of a MIF output file */
  475. TERM_PUBLIC void MIF_reset()
  476. {
  477.     /* Process if inside a MIF file and not inside a Frame */
  478.     if (mif_initialized != 0 && mif_in_frame == 0) {
  479.     /* Finish off the MIF file */
  480.     fputs("\
  481. #\n\
  482. # End of MIFFile\n", gpoutfile);
  483.  
  484.     /* Tell this terminal driver that the output is finished */
  485.     mif_initialized = 0;
  486.  
  487.     /* bs: reset frame number */
  488.     mif_frameno = -1;
  489.  
  490.     }                /* MIF file finished */
  491. }
  492.  
  493. /* Start plotting a Frame (-> graphics mode) */
  494. TERM_PUBLIC void MIF_graphics()
  495. {
  496.     int i;
  497.  
  498.     /* Process if not inside a Frame */
  499.     if (mif_initialized != 0 && mif_in_frame == 0) {
  500.     /* Tell that this terminal driver is working with a plot frame */
  501.     mif_in_frame = 1;
  502.  
  503.     /* Update frame number */
  504.     mif_frameno++;
  505.  
  506.     /* Set current position */
  507.     free_mif_line();
  508.     mif_line.fpos_x = GNP_TO_MIF(0);
  509.     mif_line.fpos_y = GNP_TO_MIF(MIF_YLAST);
  510.  
  511.     /* Set drawing properties */
  512.     mif_pen[0] = '\0';
  513.     mif_pen_width[0] = '\0';
  514.     mif_separation[0] = '\0';
  515.  
  516.     MIF_justify_text(LEFT);
  517.  
  518.     /* Reset group ID generator */
  519.     for (i = 0; i < MIF_NGROUP_ID; i++) {
  520.         mif_group_id[i].group_id = MIF_INVALID_GROUP_ID;
  521.         mif_group_id[i].group_existance = MIF_GROUP_NOT_EXISTS;
  522.     }
  523.  
  524.     /* Frame preamble */
  525.     fprintf(gpoutfile, "\
  526. #\n\
  527. # Frame number %d with plot of graphics\n\
  528. <Frame\n\
  529. \t<Pen 15>\n\
  530. \t<Fill 15>\n\
  531. \t<PenWidth  0.5 pt>\n\
  532. \t<Separation 0>\n\
  533. \t<BRect 2.000 %.3f %.3f %.3f>\n\
  534. \t<NSOffset  0.000>\n\
  535. \t<BLOffset  0.000>\n",
  536.         mif_frameno,
  537.         ((float) mif_frameno) * GNP_TO_MIF(MIF_YMAX + 100),
  538.         GNP_TO_MIF(MIF_XMAX), GNP_TO_MIF(MIF_YMAX));
  539.     }                /* Frame created */
  540. }
  541.  
  542. /* Stop plotting a Frame (-> text mode) */
  543. TERM_PUBLIC void MIF_text()
  544. {
  545.     int i;
  546.  
  547.     /* Process if inside a Frame */
  548.     if (mif_initialized != 0 && mif_in_frame != 0) {
  549.  
  550.     /* Draw pending line */
  551.     if (mif_polyline == TRUE)
  552.         put_mif_line();
  553.  
  554.     /* Group the used plot primitives */
  555.     fputs("\
  556. \t#\n\
  557. \t# Group the the objects in groups to make the chart easier to manipulate\n\
  558. \t# after it's imported into FrameMaker.\n", gpoutfile);
  559.  
  560.     for (i = 0; i < MIF_NGROUP_ID; i++) {
  561.         if (mif_group_id[i].group_id != MIF_INVALID_GROUP_ID &&
  562.         mif_group_id[i].group_existance == MIF_GROUP_EXISTS) {
  563.         fprintf(gpoutfile, "\
  564. \t<Group\n\
  565. \t\t<ID %d>\n\
  566. \t>\n", mif_group_id[i].group_id);
  567.         }
  568.     }
  569.  
  570.     /* Frame post amble */
  571.     fprintf(gpoutfile, "\
  572. >\n\
  573. # End of Frame number %d\n\
  574. #\n",
  575.         mif_frameno);
  576.  
  577.     /* Tell that this terminal driver is not working with a plot frame */
  578.     mif_in_frame = 0;
  579.     }                /* Frame finshed */
  580. }
  581.  
  582. /* Select type of line in grapics */
  583. /* NOTE: actually written to output the first time a primitive
  584.  * is drawn AFTER this call */
  585. TERM_PUBLIC void MIF_linetype(linetype)
  586. /* -2=border, -1=X/Y-axis, 0-13=lines, and 14-=mapped back */
  587. int linetype;
  588. {
  589.     /* Process if inside a Frame */
  590.     if (mif_initialized != 0 && mif_in_frame != 0) {
  591.  
  592.     /* Draw pending line */
  593.     if (mif_polyline == TRUE)
  594.         put_mif_line();
  595.  
  596.     /* Translate gnuplot pen types to MIF pen types */
  597.     if (linetype < 0) {    /* Special lines */
  598.         if (linetype == -1) {
  599.         mif_pentype = 8 + MIF_NPENS;    /* -1 */
  600.         if (mif_colour == TRUE)
  601.             sprintf(mif_separation, " <Separation 0> ");
  602.         } else {
  603.         mif_pentype = 0 + MIF_NPENS;    /* -2 or less */
  604.         if (mif_colour == TRUE)
  605.             sprintf(mif_separation, " <Separation 0> ");
  606.         }
  607.         sprintf(mif_pen_width, " <PenWidth 1.0 pt> ");
  608.     } else {        /* Normal lines */
  609.         mif_pentype = (linetype) % MIF_NPENS;    /* 0-(MIF_NPENS-1) */
  610.         sprintf(mif_pen_width, " <PenWidth 0.1 pt> ");
  611.         if (mif_colour == TRUE)
  612.         sprintf(mif_separation, " <Separation %d> ", 2 + (mif_pentype % 6));    /* 2-7 */
  613.     }
  614.  
  615.     /* Set pen type */
  616.     sprintf(mif_pen, " <Pen %d> ", mif_pattern_table[mif_pentype % MIF_NPENS]);
  617.  
  618.     }                /* Primitive processed */
  619. }
  620.  
  621. /* Draw the text horisontally or vertically (90 degrees counterclockwise) */
  622. TERM_PUBLIC int MIF_text_angle(ang)
  623. int ang;
  624. {
  625.     if (ang != 0)
  626.     mif_text_ang = MIF_TEXT_VER;
  627.     else
  628.     mif_text_ang = MIF_TEXT_HOR;
  629.  
  630.     return (TRUE);
  631. }
  632.  
  633. /* Justify following text lines (MIF_put_text()) relative to the insertion point */
  634. TERM_PUBLIC int MIF_justify_text(mode)
  635. /* NOTE: actually written to output in text primitives which are
  636.  * drawn AFTER this call */
  637. enum JUSTIFY mode;
  638. {
  639.     int rval = TRUE;
  640.  
  641.     /* Process if inside a Frame */
  642.     if (mif_initialized != 0 && mif_in_frame != 0) {
  643.     switch (mode) {
  644.     case LEFT:
  645.         sprintf(mif_justify, " <TLAlignment Left> ");
  646.         break;
  647.     case CENTRE:
  648.         sprintf(mif_justify, " <TLAlignment Center> ");
  649.         break;
  650.     case RIGHT:
  651.         sprintf(mif_justify, " <TLAlignment Right> ");
  652.         break;
  653.     default:
  654.         rval = FALSE;
  655.         break;
  656.     }
  657.  
  658.     }
  659.     /* Primitive processed */
  660.     else {
  661.     rval = FALSE;
  662.     }
  663.  
  664.     return (rval);
  665. }
  666.  
  667. /* Draw a vector from current position to (x, y) and change current position. */
  668. /* NOTE: actually written to output the first time another primitive
  669.  * is called AFTER this call */
  670. TERM_PUBLIC void MIF_vector(x, y)
  671. unsigned int x, y;
  672. {
  673.     /* Process if inside a Frame */
  674.     if (mif_initialized != 0 && mif_in_frame != 0) {
  675.  
  676.     /* Setup the vector as a part of the line */
  677.     insert_mif_line(GNP_TO_MIF(x), GNP_TO_MIF(MIF_YLAST - (int) y));
  678.  
  679.     /* Draw pending line -> vector */
  680.     if (mif_polyline == FALSE)
  681.         put_mif_line();
  682.  
  683.     }                /* Vector processed */
  684. }
  685.  
  686. /* Move current position */
  687. TERM_PUBLIC void MIF_move(x, y)
  688. unsigned int x, y;
  689. {
  690.     /* Process if inside a Frame */
  691.     if (mif_initialized != 0 && mif_in_frame != 0) {
  692.  
  693.     /* Draw pending line */
  694.     if (mif_polyline == TRUE)
  695.         put_mif_line();
  696.  
  697.     mif_line.fpos_x = GNP_TO_MIF(x);
  698.     mif_line.fpos_y = GNP_TO_MIF(MIF_YLAST - (int) y);
  699.     }
  700. }
  701.  
  702.  
  703. /* set font */
  704. static void MIF_set_font(font)
  705. char *font;
  706. {
  707.     if (font != mif_font) {
  708.     fprintf(gpoutfile, "\t\t<Font\n\t\t\t<FTag `%s'>\n\t\t>\n", font);
  709.     mif_font = font;
  710.     }
  711. }
  712.  
  713.  
  714. /* Draw the text string str at (x, y). Adjust according to MIF_justify_text().
  715.  * Change current position. */
  716. TERM_PUBLIC void MIF_put_text(x, y, str)
  717. unsigned int x, y;
  718. char str[];
  719. {
  720.     /* Process if inside a Frame */
  721.     if (mif_initialized != 0 && mif_in_frame != 0) {
  722.  
  723.     /* Draw pending line */
  724.     if (mif_polyline == TRUE)
  725.         put_mif_line();
  726.  
  727.     /* Adjust current position for text-graphics alignment */
  728.     MIF_move(x, y - MIF_VCHAR / 5);
  729.  
  730.     if (strlen(str) > 0) {
  731.  
  732.         /* Draw the text */
  733.         fprintf(gpoutfile, "\t<TextLine <GroupID %d> %s %s %s\n",
  734.             MIF_PEN_TO_GROUP(mif_pentype), mif_pen,
  735.             mif_pen_width, mif_separation);
  736.  
  737.         MIF_set_font(zgnuplot);
  738.  
  739.         fprintf(gpoutfile, "\
  740. \t\t<TLOrigin  %.3f %.3f> %s %s <String `%s'>\n\
  741. \t>\n",
  742.             mif_line.fpos_x, mif_line.fpos_y, mif_justify,
  743.             (mif_text_ang == MIF_TEXT_VER) ? "<Angle 90>" : "",
  744.             str);
  745.  
  746.         /* Register the used group ID */
  747.         proc_group_id(MIF_PEN_TO_GROUP(mif_pentype));
  748.  
  749.         /* Avoid to redraw this. The MIF system should remember it. */
  750.         mif_pen[0] = '\0';
  751.         mif_pen_width[0] = '\0';
  752.         mif_separation[0] = '\0';
  753.  
  754.         mif_justify[0] = '\0';    /* Independent of linetype */
  755.     }
  756.     }                /* Text processed */
  757. }
  758.  
  759.  
  760. /* Insert one point in the line */
  761. static int insert_mif_line(fx, fy)
  762. double fx, fy;
  763. {
  764.     int rval = TRUE;
  765.  
  766.     if ((mif_line.prev->next = (struct mif_line *) gp_alloc(sizeof(struct mif_line),
  767.     "MIF driver")) != (struct mif_line *) NULL) {
  768.     /* Link */
  769.     mif_line.prev->next->next = &mif_line;
  770.     mif_line.prev->next->prev = mif_line.prev;
  771.     mif_line.prev = mif_line.prev->next;
  772.  
  773.     /* Fill */
  774.     mif_line.prev->fpos_x = fx;
  775.     mif_line.prev->fpos_y = fy;
  776.  
  777.     rval = TRUE;
  778.     } else {            /* Failed to allocate */
  779.     /* Relink */
  780.     mif_line.prev->next = &mif_line;
  781.  
  782.     rval = FALSE;
  783.     }
  784.  
  785.     return (rval);
  786. }
  787.  
  788. /* Register group ID. Update group ID existance. */
  789. /* Returns:     1       group_id belongs to a MIF group
  790.         0       group_id does not belong to a MIF group
  791.            -1       not inside a Frame
  792.            -2       group ID list is full
  793.  */
  794. static int proc_group_id(group_id)
  795. int group_id;
  796. {
  797.     int i, rval = 0;
  798.  
  799.     /* Process if inside a Frame */
  800.     if (mif_initialized != 0 && mif_in_frame != 0) {
  801.  
  802.     /* Find out the group ID, or a free group ID slot index. */
  803.     for (i = 0; i < MIF_NGROUP_ID &&
  804.          mif_group_id[i].group_id != MIF_INVALID_GROUP_ID &&
  805.          mif_group_id[i].group_id != group_id;
  806.          i++) {
  807.         /* Don't check the group_existance variable */
  808.     }
  809.  
  810.     if (i < MIF_NGROUP_ID) {
  811.         if (mif_group_id[i].group_id == MIF_INVALID_GROUP_ID) {
  812.         /* Register as new group ID for eventual use as MIF group */
  813.         mif_group_id[i].group_id = group_id;
  814.         mif_group_id[i].group_existance = MIF_GROUP_NOT_EXISTS;
  815.         } else {
  816.         /* If second use of this group ID -> create a new MIF group */
  817.         if (mif_group_id[i].group_id == group_id) {
  818.             mif_group_id[i].group_existance = MIF_GROUP_EXISTS;
  819.             /* NOTE: a group MUST have at least two members. */
  820.             rval = 1;
  821.         }
  822.         }
  823.     } else {
  824.         rval = -2;        /* No place for this group ID in the list */
  825.     }
  826.  
  827.     }
  828.     /* Group ID processed */
  829.     else {
  830.     rval = -1;        /* Not inside a Frame */
  831.     }
  832.  
  833.     /* Return MIF group status */
  834.     return (rval);
  835. }
  836.  
  837.  
  838. #endif
  839.  
  840.  
  841. #ifdef TERM_TABLE
  842.  
  843. TERM_TABLE_START(mif_driver)
  844.     "mif", "Frame maker MIF 3.00 format",
  845.     MIF_XMAX, MIF_YMAX, MIF_VCHAR, MIF_HCHAR,
  846.     MIF_VTIC, MIF_HTIC, MIF_options, MIF_init, MIF_reset,
  847.     MIF_text, null_scale, MIF_graphics, MIF_move, MIF_vector,
  848.     MIF_linetype, MIF_put_text, MIF_text_angle,
  849.     MIF_justify_text, MIF_point, do_arrow, set_font_null
  850. TERM_TABLE_END(mif_driver)
  851.  
  852. #undef LAST_TERM
  853. #define LAST_TERM mif_driver
  854.  
  855. #endif
  856. #endif /* TERM_PROTO_ONLY */
  857.  
  858. #ifdef TERM_HELP
  859. START_HELP(mif)
  860. "1 mif",
  861. "?commands set terminal mif",
  862. "?set terminal mif",
  863. "?set term mif",
  864. "?terminal mif",
  865. "?term mif",
  866. "?mif",
  867. " The `mif` terminal driver produces Frame Maker MIF format version 3.00.  It",
  868. " plots in MIF Frames with the size 15*10 cm, and plot primitives with the same",
  869. " pen will be grouped in the same MIF group.  Plot primitives in a `gnuplot`",
  870. " page will be plotted in a MIF Frame, and several MIF Frames are collected in",
  871. " one large MIF Frame.  The MIF font used for text is \"Times\".",
  872. "",
  873. " Several options may be set in the MIF 3.00 driver.",
  874. "",
  875. " Syntax:",
  876. "       set terminal mif {colour | monochrome} {polyline | vectors}",
  877. "                        {help | ?}",
  878. "",
  879. " `colour` plots lines with line types >= 0 in colour (MIF sep. 2--7) and",
  880. " `monochrome` plots all line types in black (MIF sep. 0).",
  881. " `polyline` plots curves as continuous curves and `vectors` plots curves as",
  882. " collections of vectors.",
  883. " `help` and `?` print online help on standard error output---both print a",
  884. " short description of the usage; `help` also lists the options;",
  885. "",
  886. " Examples:",
  887. "       set term mif colour polylines    # defaults",
  888. "       set term mif                     # defaults",
  889. "       set term mif vectors",
  890. "       set term mif help"
  891. END_HELP(mif)
  892. #endif /* TERM_HELP */
  893.